<?php
namespace App\Http\Controllers\Api;

use App\Api\Helpers\MoveNumber;
use App\Api\Helpers\SendMessage;
use App\Http\Controllers\Controller;
use App\Http\Middleware\ApiLog;
use App\Models\MShopOrders;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;
use EasyWeChat\Factory;

/**
 * 订单
 *
 */
class NotifyController extends Controller {
    use MoveNumber;
    use SendMessage;
    /**
     * 支付回调
     *
     */
    public function notify_wx()
    {
        writeLogs([], '已进入到微信回调', 'notify'); // 写入日志记录
        $notify_data = file_get_contents("php://input");
        $notify_data = $this->from_xml($notify_data);
        writeLogs($notify_data, '回调返回数据', 'notify'); // 写入日志记录
        if (!$notify_data) {
            writeLogs($notify_data, '未接收到信息', 'notify'); // 写入日志记录
            $notify_data = $GLOBALS['HTTP_RAW_POST_DATA'] ?: '';
        }
        // 验签
        $return_data = $this->query_weixin_sign($notify_data);
        if (!$return_data) {
            writeLogs($notify_data, '验签失败', 'notify'); // 写入日志记录
            echo 'fail';
            die;
        }
        writeLogs($notify_data, '验签通过', 'notify'); // 写入日志记录

        if ($notify_data['return_code'] == 'SUCCESS' && $notify_data['result_code'] == 'SUCCESS') {
            $order_id = $notify_data['out_trade_no'];
            $check_data = MShopOrders::where(['order_sn' => $order_id])->first();
            if ($check_data['status'] == 0) {
                // 事务开启
                DB::beginTransaction();
                try {
                    // 更改订单状态
                    $order_status = $check_data['is_normal'] == 1 ? 3 : 1;
                    $result = MShopOrders::where(['order_sn' => $order_id])->update(['status'=> $order_status, 'pay_sn'=> $notify_data['transaction_id'],'pay_time'=> date('Y-m-d H:i:s', time())]);
                    if ( !$result ) {
                        DB::rollBack();
                    }
                    if( $order_status == 1 ){
                        // 创建订单  预占号
                        $data = $this->make_phone_order($check_data);
                        if ( $data['code'] == 201 ) {
                            // 预占号失败
                            $res = MShopOrders::where(['order_sn' => $order_id])->update(['status'=> 3, 'is_normal'=> 1, 'cancel_reason'=> $data['msg']]);
                        } else {
                            // 预占号成功  更新订单数据
                            $res = MShopOrders::where(['order_sn' => $order_id])->update(['order_operator'=> $data['order_id']]);
                        }
                    } else {
                        $res = true;
                    }

                    // 发送模板消息
                    $this->buy_success($check_data);

                    if ( !$res ) {
                        DB::rollBack();
                        throw new \LogicException('更新预占号订单失败', 202);
                    }
                    DB::commit();
                    echo 'success';
                    die;
                } catch (\Exception $e) {
                    writeLogs($notify_data, "支付回调更新失败，失败code：" . $e->getCode() . ",失败msg：" . $e->getMessage(), 'notify'); // 写入日志记录
                    DB::rollBack();
                    echo 'fail';
                    die;
                }
            }
            echo "success";
            die;
        }
    }

    /**
     * 生成签名 - 重写该方法
     * @param array $data  配置对象
     *
     * @return float
     */
    public function query_weixin_sign($data)
    {
        $wxconfig = config("wechat.payment.default");
        //签名步骤一：按字典序排序参数
        ksort($data);
        $checkSign = $data['sign'];
        unset($data['sign']);
        $string = $this->to_url_params($data);
        //签名步骤二：在string后加入KEY
        $string = $string . "&key=".$wxconfig['key'];
        //签名步骤三：MD5加密或者HMAC-SHA256
        if(strlen($checkSign) <= 32){
            //如果签名小于等于32个,则使用md5验证
            $string = md5($string);
        } else {
            //是用sha256校验
            $string = hash_hmac("sha256",$string ,$wxconfig['key']);
        }
        //签名步骤四：所有字符转为大写
        $result = strtoupper($string);
        writeLogs(['sign'=> $result, 'checksign'=> $checkSign], '回调数据签名验证', 'notify'); // 写入日志记录
        if($result == $checkSign) {
            return true;
        } else {
            return false;
        }
    }

    public function from_xml($xml)
    {
        if (!$xml) {
            echo "xml数据异常！";
        }
        //将XML转为array  禁止引用外部xml实体
        libxml_disable_entity_loader(true);
        $data = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
        return $data;
    }

    /**
     * 格式化参数格式化成url参数
     * @param array $datas 参数
     *
     * @return string
     */
    private function to_url_params($datas)
    {
        $buff = "";
        foreach ($datas as $k => $v) {
            if ($k != "sign" && $v != "" && !is_array($v)) {
                $buff .= $k . "=" . $v . "&";
            }
        }
        $buff = trim($buff, "&");
        return $buff;
    }

    /**
     * 购买成功发送消息
     *
     */
    public function buy_success($order_info){
        $template_id = 'RnWD8sDGTeH99RO_b4XYJC3gSreCBTgVV__zsAeien8';
        $user_info = DB::table('users')->where(['id'=> $order_info->uid])->first();
        $goods_info = DB::table('shop_goods')->where(['id'=> $order_info->goods_id])->first();
        $data = [
            'first'    => '恭喜购买成功',
            'keyword1' => $order_info->phone,
            'keyword2' => $goods_info? $goods_info->name : '移动套餐',
            'keyword3' => $order_info->price,
            'keyword4' => '购买成功',
            'remark' => '如有疑问，请联系客服',
        ];
        $this->sendTemplateMessage($user_info->watchid, $template_id, $data);
        return true;
    }
}
